package com.bms.cfcmms.service;

import com.bms.cfcmms.dao.ModuleDao;
import com.bms.cfcmms.model.system.module.Module;
import com.bms.cfcmms.util.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by carl on 2016/4/11.
 */
public class ModuleService {

    private static final String BEAN_CFCMMS_ROOT = "com.dms.cfcmms.model";
    private static final String BEAN_DSA_ROOT = "com.dms.dsa.model";
    private static Logger log = LoggerFactory.getLogger(ModuleService.class);
    private static ModuleDao moduleDao = null;
    private static Map<String, Module> modules = new HashMap<>();
    private static List<String> beanDirs = new ArrayList<>();
    private static Map<String, Class<?>> classMap = new HashMap<String, Class<?>>();

    private ModuleService() {}
    /**
     * 获取所有子包路径.
     * <p/>
     * 检查某个包下面是否还有子包存在，如果有的话，也加入到检测bean的目录之中，这是一个递归的过程
     *
     * @param packages 存储所有的包路径
     * @param dirname  父包的路径
     * @return 无返回结果，结果存在packages中
     */
    private static void getSubPackageName(List<String> packages, String dirname, String parent) {
        // 如果是window系统，空格用%20来表示的
        File file = new File(dirname.replace("%20", " "));
        File[] childFiles = file.listFiles();
        if (childFiles != null) {
            for (File childFile : childFiles) {
                if (childFile.isDirectory()) {
                    int childIndex = childFile.getPath().lastIndexOf(File.separator);
                    String path = parent + childFile.getPath().substring(childIndex + 1);
                    packages.add(path);
                    getSubPackageName(packages, childFile.getPath(), path);
                }
            }
        }
    }

    /**
     * 根据包名，取得该包下的下一级目录的名字，没有考虑递归.
     *
     * @param packageName 父包名
     * @return 子包名称
     */
    private static List<String> getPackageName(String packageName) {
        List<String> packages = new ArrayList<>();
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        String packagePath = packageName.replace(".", "/");
        URL url = loader.getResource(packagePath);
        if (url != null) {
            String type = url.getProtocol();
            if ("file".equalsIgnoreCase(type)) {
                // 如果是window系统，空格用%20来表示的
                File file = new File(url.getPath().replace("%20", " "));
                File[] childFiles = file.listFiles();
                if (childFiles != null) {
                    dealSubPackageName(packages, childFiles);
                }
            }
        }
        return packages;
    }

    private static void dealSubPackageName(List<String> packages, File[] childFiles) {
        for (File childFile : childFiles) {
            if (childFile.isDirectory()) {
                int childPath = childFile.getPath().lastIndexOf(File.separator);
                String path = childFile.getPath().substring(childPath + 1);
                packages.add(path);
                getSubPackageName(packages, childFile.getPath(), path + ".");
            }
        }
    }

    private static List<String> getBeanDirs() {
        if (beanDirs.isEmpty()) {
            beanDirs.add(BEAN_CFCMMS_ROOT);
            beanDirs.add(BEAN_DSA_ROOT);
            List<String> subPackages = getPackageName(BEAN_CFCMMS_ROOT);
            for (String subPath : subPackages) {
                beanDirs.add(BEAN_CFCMMS_ROOT + "." + subPath);
            }

            subPackages = getPackageName(BEAN_DSA_ROOT);
            for (String subPath : subPackages) {
                beanDirs.add(BEAN_DSA_ROOT + "." + subPath);
            }
        }
        return beanDirs;
    }

    /**
     * 获取moduleName模块的类信息.
     *
     * @param moduleName 模块名称
     * @return 此模块的类信息
     */
    public static Class<?> getModuleBeanClass(String moduleName) {
        Class<?> moduleClass = classMap.get(moduleName);
        if (moduleClass != null) {
            return moduleClass;
        }
        for (String dir : getBeanDirs()) {
            try {
                moduleClass = Class.forName(dir + "." + moduleName);
                classMap.put(moduleName, moduleClass);
                break;
            } catch (ClassNotFoundException e) {
                log.error("", e);
            }
        }
        if (moduleClass == null) {
            Object[] params = {BEAN_CFCMMS_ROOT, BEAN_DSA_ROOT};
            log.error(SpringUtils.getMessage("file.notfind", params));
        }
        return moduleClass;
    }

    /**
     * 根据模块 as name 号取得模块定义.
     * 系统启动时会将所有的模块信息保存在此处
     *
     * @param name 模块名称
     * @return 返回name模块的_Module对象
     */
    public static Module getModuleWithAsName(String name) {
        Module module = modules.get(name);
        if (module == null) {
            getModuleDao();

            module = moduleDao.queryForObjectByName(name);
            if (module != null) {
                modules.put(name, module);
            } else {
                log.error(SpringUtils.getMessage("module.notfind", name));
            }
        }
        return module;
    }

    private static ModuleDao getModuleDao() {
        if (moduleDao == null) {
            moduleDao = SpringUtils.getBean(ModuleDao.class);
        }
        return moduleDao;
    }
}
